package Q5_04_Next_Number; public class QuestionB { public static int getNext(int n) { int c = n; int c0 = 0; int c1 = 0; while (((c & 1) == 0) && (c != 0)) { c0++; c >>= 1; } while ((c & 1) == 1) { c1++; c >>= 1; } /* If c is 0, then n is a sequence of 1s followed by a sequence of 0s. This is already the biggest * number with c1 ones. Return error. */ if (c0 + c1 == 31 || c0 + c1 == 0) { return -1; } int pos = c0 + c1; // position of right-most non-trailing zero (where the right most bit is bit 0) /* Flip the right-most non-trailing zero (which will be at position pos) */ n |= (1 << pos); // Flip right-most non-trailing zero /* Clear all bits to the right of pos. * Example with pos = 5 * (1) Shift 1 over by 5 to create 0..0100000 [ mask = 1 << pos ] * (2) Subtract 1 to get 0..0011111 [ mask = mask - 1 ] * (3) Flip all the bits by using '~' to get 1..1100000 [ mask = ~mask ] * (4) AND with n */ n &= ~((1 << pos) - 1); // Clear all bits to the right of pos /* Put (ones-1) 1s on the right by doing the following: * (1) Shift 1 over by (ones-1) spots. If ones = 3, this gets you 0..0100 * (2) Subtract one from that to get 0..0011 * (3) OR with n */ n |= (1 << (c1 - 1)) - 1; return n; } public static int getPrev(int n) { int temp = n; int c0 = 0; int c1 = 0; while ((temp & 1) == 1) { c1++; temp >>= 1; } /* If temp is 0, then the number is a sequence of 0s followed by a sequence of 1s. This is already * the smallest number with c1 ones. Return -1 for an error. */ if (temp == 0) { return -1; } while (((temp & 1) == 0) && (temp != 0)) { c0++; temp >>= 1; } int p = c0 + c1; // position of right-most non-trailing one (where the right most bit is bit 0) /* Flip right-most non-trailing one. * Example: n = 00011100011. * c1 = 2 * c0 = 3 * pos = 5 * * Build up a mask as follows: * (1) ~0 will be a sequence of 1s * (2) shifting left by p + 1 will give you 11.111000000 (six 0s) * (3) ANDing with n will clear the last 6 bits * n is now 00011000000 */ n &= ((~0) << (p + 1)); // clears from bit p onwards (to the right) /* Create a sequence of (c1+1) 1s as follows * (1) Shift 1 to the left (c1+1) times. If c1 is 2, this will give you 0..001000 * (2) Subtract one from that. This will give you 0..00111 */ int mask = (1 << (c1 + 1)) - 1; // Sequence of (c1+1) ones /* Move the ones to be right up next to bit p * Since this is a sequence of (c1+1) ones, and p = c1 + c0, we just need to * shift this over by (c0-1) spots. * If c0 = 3 and c1 = 2, then this will look like 00...0011100 * * Then, finally, we OR this with n. */ n |= mask << (c0 - 1); return n; } public static void binPrint(int i) { System.out.println(i + ": " + Integer.toBinaryString(i)); } public static void main(String[] args) { int i = 13948; int p1 = getPrev(i); int n1 = getNext(i); Tester.binPrint(p1); Tester.binPrint(n1); } }